Release 10.1A: OpenEdge Getting Started:
Object-oriented Programming


Passing object reference parameters

When an application passes an object reference to a method, user-defined function, or procedure, the effect is identical to assigning one object reference to another, with regard to the parameter mode (INPUT, INPUT-OUTPUT, or OUTPUT). Thus, the assignment rules can be summarized by designating the object that provides the reference as the source and the object that receives the reference as the target. The target object reference definition can be:

  1. The same type as the source (for example, to rCustObj from rCustObj).
  2. A super class of the source (for example, to rCommonObj from rCustObj).
  3. An interface that the source implements (for example, to rIBusObj from rCustObj).

For more information on the rules for assigning object references, see the "Assigning object references" section.

Following are a series of examples that demonstrate the passing of object reference parameters for INPUT, INPUT-OUTPUT, and OUTPUT. These examples highlight code from the Main class shown previously (see the "Defining an object reference as a variable" section) and related sample classes that are described and fully listed in the "Sample classes" section. Refer to these samples for referenced class listings that are not shown in this section.

When passing an INPUT parameter, the caller is the source of the assignment and the invoked method is the target of the assignment. Therefore, the invoked method must define a parameter that is the same class as the INPUT object reference, or a super class or interface of the INPUT object reference. If the invoked method has as its parameter a super class or interface object reference, the invoked method can only call those methods that are defined by that super class or interface. If the invoked method attempts to call methods that are not defined in the super class or interface, the compiler generates an error.

The following examples pass an INPUT parameter:

CLASS Main: 
    DEFINE PRIVATE VARIABLE rCustObj  
        AS CLASS acme.myObjs.CustObj NO-UNDO. 
    ... 
    DEFINE PRIVATE VARIABLE rHelperClass 
        AS CLASS acme.myObjs.Common.HelperClass NO-UNDO. 
    ... 
    METHOD PUBLIC VOID ObjectInfo( ): 
        rHelperClass:ListDate(INPUT rCustObj). 
        MESSAGE rCustObj:timestamp.  
        ... 
    END METHOD. 
    ... 
END CLASS. 

CLASS acme.myObjs.Common.HelperClass: 
    METHOD PUBLIC VOID ListDate  
            (INPUT rObject AS CLASS acme.myObjs.Common.CommonObj): 
        /* Timestamp this object */ 
        IF VALID-OBJECT(rObject) THEN 
            rObject:updateTimestamp( ). 
        ELSE 
            rError:Alert("Not a valid object"). 
    END METHOD. 
END CLASS. 

The previous example shows an acme.myObjs.CustObj instance passed as input to the ListDate( ) method, which is defined to take an acme.myObjs.Common.CommonObj (super class of acme.myObjs.CustObj). Note that the updateTimestamp( ) method invoked on the input object reference only exists in acme.myObjs.Common.CommonObj. (For a listing of this class, see the "Calling methods from inside a class" section.) This method can be invoked on any object that is a subclass of acme.myObjs.Common.CommonObj. After the invocation of the method in Main, the program accesses the public data member timestamp, which is also defined in acme.myObjs.Common.CommonObj. For more information on acme.myObjs.Common.CommonObj, see the sample classes in the "Sample classes" section.

When you pass an INPUT-OUTPUT object then the corresponding parameter must have the same class as the INPUT-OUTPUT object. Because the parameter is being passed in both directions, its type must match exactly.

The following examples pass an INPUT-OUTPUT parameter:

CLASS Main: 
    DEFINE PRIVATE VARIABLE rCustObj  
        AS CLASS acme.myObjs.CustObj NO-UNDO. 
    ... 
    DEFINE PRIVATE VARIABLE rHelperClass 
        AS CLASS acme.myObjs.Common.HelperClass NO-UNDO. 
    ... 
    METHOD PUBLIC VOID ObjectInfo( ): 
        rHelperClass:ListNames(INPUT-OUTPUT rCustObj). 
        rCustObj:CheckCredit( ). 
        ... 
    END METHOD. 
    ... 
END CLASS. 

CLASS acme.myObjs.Common.HelperClass: 
    DEFINE PRIVATE VARIABLE rCustObj AS CLASS acme.myObjs.CustObj NO-UNDO. 
    ... 
    METHOD PUBLIC VOID ListNames  
            (INPUT-OUTPUT prCustObj AS CLASS acme.myObjs.CustObj): 
        DEFINE VARIABLE i AS INTEGER NO-UNDO. 
        DO i = 1 to prCustObj:iNumCusts: 
            CREATE ttCustNames. 
            ASSIGN 
                ttCustNames.CustName = prCustObj:GetCustomerName(INPUT i) 
                ttCustNames.CustNum  = i. 
        END. 
        rCustObj = prCustObj. 
        prCustObj = NEW acme.myObjs.CustObj( ). 
    END METHOD. 
END CLASS. 

The previous example shows an acme.myObjs.CustObj instance passed as an INPUT-OUTPUT parameter to the ListNames( ) method in acme.myObjs.Common.HelperClass. In this case, the type on both sides (the passed object reference and the parameter definition) have to be exactly the same, in this case acme.myObjs.CustObj. The ListNames( ) method first uses the input object reference and stores the value in its PRIVATE data member, rCustObj. Then, ListNames( ) instantiates a new instance of acme.myObjs.CustObj to return as an output object reference with the same parameter, which is used back in the Main class to invoke the CheckCredit( ) method defined in acme.myObjs.CustObj.

When passing an OUTPUT parameter, the caller is the target of the assignment and the invoked method is the source of the assignment. Therefore, the caller method must define a parameter that is the same class as the OUTPUT object reference, or a super class or interface of the OUTPUT object reference. Once again, if the caller has as its parameter a super class or interface object reference, the caller can only invoke those methods that are defined by the super class or interface, respectively. If the caller attempts to invoke a method that is not defined in the super class, the compiler generates an error.

The following examples pass an OUTPUT parameter:

CLASS Main: 
    ... 
    DEFINE PRIVATE VARIABLE rIBusObj  
        AS CLASS acme.myObjs.Interfaces.IBusObj NO-UNDO. 
    ... 
    DEFINE PRIVATE VARIABLE rHelperClass 
        AS CLASS acme.myObjs.Common.HelperClass NO-UNDO. 
    ... 
    METHOD PUBLIC VOID ObjectInfo( ): 
        rHelperClass:ReportOutput(OUTPUT rIBusObj). 
        rIBusObj:logObj(INPUT "Customer.out"). 
        ... 
    END METHOD. 
    ... 
END CLASS. 

CLASS acme.myObjs.Common.HelperClass: 
    DEFINE PRIVATE VARIABLE rCustObj AS CLASS acme.myObjs.CustObj NO-UNDO. 
    ... 
    METHOD PUBLIC VOID ReportOutput  
            (OUTPUT prInterface AS CLASS acme.myObjs.Interfaces.IBusObj): 
        /* Send the PRIVATE CustObj instance back to be printed */ 
        IF VALID-OBJECT(rCustObj) THEN 
            prInterface = rCustObj. 
        ELSE 
            rError:Alert("The object is not valid"). 
    END METHOD. 
END CLASS. 

In the previous example, the ReportOutput( ) method is invoked with an OUTPUT parameter defined as an object reference to the acme.myObjs.Interfaces.IBusObj interface. Through the OUTPUT parameter, the method in acme.myObjs.Common.HelperClass returns an object reference to acme.myObjs.CustObj (which happens to be privately maintained by the class). This works because acme.myObjs.CustObj implements the acme.myObjs.Interfaces.IBusObj interface. The class acme.myObjs.Common.HelperClass can return any object that implements acme.myObjs.Interfaces.IBusObj. Note that after returning from ReportOutput( ), the logObj( ) method is invoked on the returned object reference. This method is specified in the interface and implemented in acme.myObjs.CustObj. It would be invalid to invoke a method on the returned object reference that is not specified in the interface.


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095